package com.topnav.mc.base.mc;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.js.lib.annotation.ApiLogger;
import com.js.lib.cache.SysCache;
import com.js.lib.result.ApiResult;
import com.js.lib.result.Result;
import com.topnav.mc.common.Constant;
import com.topnav.mc.validator.ValidList;
import com.topnav.mc.validator.group.IAdd;
import com.topnav.mc.validator.group.IDelete;
import com.topnav.mc.validator.group.ISelect;
import com.topnav.mc.validator.group.IUpdate;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Constructor;
import java.util.List;

/**
 * Controller 通用接口类
 * @param <T>  实体类，对应数据库
 * @param <I>  结果类，通过多表联合查询的结果
 * @param <P>  参数类，查询时使用的参数类，比如时间字段，查询果可能会有开始时间，结束时间
 * @param <Service> 业务实现接口类
 * @param <W> QueryWrapper类
 */
@Slf4j
public abstract class McController<T,I,P,Service extends IMcService<T,I,P>,W extends McWrapper<P>> {
    @Autowired
    private SysCache sysCache;

    @Autowired(required = false)
    protected Service baseService;

    protected Class<W> wrapperClass = (Class<W>) ReflectionKit.getSuperClassGenericType(getClass(), 4);
    protected Class<P> paramClass = (Class<P>) ReflectionKit.getSuperClassGenericType(getClass(), 2);


    /**
     * 新增
     * id=null
     * @param data
     * @return
     */
    @ApiLogger(apiName="/add")
    @ApiOperation(value = "新增")
    @PostMapping("/add")
    @ResponseBody
    public Result add(@Validated(IAdd.class) @RequestBody T data) {
        baseService.save(data);
        return Result.ok(data);
    }


    /**
     * 批量新增
     * id=null
     * @param datas
     * @return
     */
    @ApiLogger(apiName="/adds")
    @ApiOperation(value = "批量新增")
    @PostMapping("/adds")
    @ResponseBody
    public Result adds(@Validated(IAdd.class) @RequestBody ValidList<T> datas) {
        baseService.saveBatch(datas,datas.size());
        return Result.ok();
    }


    /**
     * 修改，只修改属性不为空的字段
     * id != null
     * @param data
     * @return
     */
    @ApiLogger(apiName="/update")
    @ApiOperation(value = "修改(为空的参数不更新)")
    @PostMapping("/update")
    @ResponseBody
    public Result update(@Validated(IUpdate.class) @RequestBody T data) {
        baseService.updateById(data);
        return Result.ok(data);
    }

    @ApiOperation(value = "删除")
    @PostMapping("/delete")
    @ResponseBody
    public Result delete(@Validated(IDelete.class) @RequestBody T data) {
        baseService.remove(new QueryWrapper<>(data));
        return Result.ok();
    }

    @PostMapping({"/delete/{id}"})
    @ResponseBody
    public Result delete(@PathVariable Long id) {
        this.baseService.removeById(id);
        return Result.ok();
    }

    /**
     * 按条查一条，一般只按id查
     * @param p
     * @return
     */
    @ApiOperation(value = "只查一条")
    @PostMapping("/get/one")
    @ResponseBody
    public ApiResult<I> queryExtenGetOne(@Validated(ISelect.class) @RequestBody P p) {
        I datas = baseService.getOneInfo(getNewWrapper(p),false);
        return (ApiResult<I>) ApiResult.ok(datas);
    }

    /**
     * 查询所有数据
     * 结果类为 I
     * @return
     */
    @ApiLogger(apiName="/query/list")
    @PostMapping("/query/list")
    @ApiOperation(value = "查询所有")
    @ResponseBody
    public ApiResult<List<I>>  queryList() {
        List datas = baseService.listInfo();
        return (ApiResult<List<I>>) ApiResult.ok(datas);
        //return Result.ok(datas);
    }

    /**
     * 按条件查询
     * 参数类 P
     * 结果类 I
     * @param p
     * @return
     */
    @ApiOperation(value = "按条件查询")
    @PostMapping("/query/list/where")
    @ResponseBody
    public ApiResult<List<I>> queryExtenWhereList(@Validated(ISelect.class) @RequestBody P p) {
/*
        List datas = baseService.listInfo(getNewWrapper(p));
        return Result.ok(datas);
*/
        List datas = baseService.listInfo(getNewWrapper(p));
        return (ApiResult<List<I>>) ApiResult.ok(datas);

    }

    /**
     * 分页查询所有
     * 参数类 P
     * 结果类 I
     * @param page
     * @return
     */
    @ApiOperation(value = "分页查询所有")
    @PostMapping("/query/page")
    @ResponseBody
    public ApiResult<List<I>> queryPage(@Validated(IPage.class) @RequestBody McPage<P> page) {
        /*String token = MDC.get(Constant.MDC_TOEKN);*/

/*
        Page<I> page1 = baseService.pageInfo(page.getPage());
        return Result.ok(page1);
*/
        Page<I> page1 = baseService.pageInfo(page.getPage(), getNewWrapper(page.getWhere()));
        return (ApiResult<List<I>>) ApiResult.ok(page1);

    }


    /**
     * 按条件分页查询
     * 参数类 P
     * 结果类 I
     * @param page
     * @return
     */
    @ApiOperation(value = "按条件分页查询")
    @PostMapping("/query/extent/page")
    @ResponseBody
    public Result queryExtenPage(@Validated(IPage.class) @RequestBody McPage<P> page) {
        Page<I> page1 = baseService.pageInfo(page.getPage(), getNewWrapper(page.getWhere()));
        return Result.ok(page1);
    }



    /**
     * 生成查询条件的 Wrapper
     * @param p
     * @return
     */
    protected W getNewWrapper(P p) {
        try{
            /** 带参数的反射构造 */
            Constructor<W> c=wrapperClass.getConstructor(paramClass);//获取有参构造
            W w= c.newInstance(p);
            return w;
        }catch (InstantiationException e1){
            log.error(">>>>>>>InstantiationException: {}",e1);
        }catch (IllegalAccessException e2){
            log.error(">>>>>>>IllegalAccessException: {}",e2);
        }catch (NoSuchMethodException e3){
            log.error(">>>>>>>NoSuchMethodException: {}",e3);
        }catch (SecurityException e4){
            log.error(">>>>>>>SecurityException: {}",e4);
        }catch (Exception e5){
            log.error(">>>>>>>Exception: {}",e5);
        }

        return null;
    }
}
